﻿#include "Utils.h"
#include <random>
#include <Windows.h>
#include <iostream>
static const Postion s_postionArry[21] =
{
    Postion::DEFAULT,
    Postion::EAST, Postion::NORTH, Postion::WEST, Postion::SOUTH,
    Postion::EAST, Postion::NORTH, Postion::WEST, Postion::SOUTH,
    Postion::EAST, Postion::NORTH, Postion::WEST, Postion::SOUTH,
    Postion::EAST, Postion::NORTH, Postion::WEST, Postion::SOUTH,
    Postion::EAST, Postion::NORTH, Postion::WEST, Postion::SOUTH
};

Postion Utils::getNextShowPostion(Postion ps)
{
    short nextPostion = (ps - 1);
    if (nextPostion == -1)
    {
        return Postion::SOUTH;
    }
    return Postion(nextPostion);
}

Postion Utils::getNextDispatchPostion(Postion ps)
{
    short nextPostion = (ps + 1);
    if (nextPostion == 4)
    {
        return Postion::EAST;
    }
    return Postion(nextPostion);
}

const std::string Utils::chessType2Str(ChessType tp)
{
    switch (tp)
    {
    case ChessType::BING:
    {
        return "BING";
    }
    case ChessType::WAN:
    {
        return "WAN_";
    }
    case ChessType::TIAO:
    {
        return "TIAO";
    }
    case ChessType::DF:
    {
        return "DF__";
    }
    case ChessType::XF:
    {
        return "XF__";
    }
    case ChessType::NF:
    {
        return "NF__";
    }
    case ChessType::BF:
    {
        return "BF__";
    }
    case ChessType::Zh:
    {
        return "ZH__";
    }
    case ChessType::Fa:
    {
        return "FA__";
    }
    case ChessType::Bai:
    {
        return "BAI_";
    }
    default:
        break;
    }
    return "default";
}

const std::string Utils::chess2Str(const Chess& chess)
{
    std::stringstream chessSS;

    switch (chess.type)
    {
    case ChessType::BING:
    {
        chessSS << "[" << chess.count << "]";
        break;
    }
    case ChessType::WAN:
    {
        chessSS << "(" << chess.count << ")";
        break;
    }
    case ChessType::TIAO:
    {
        chessSS << "{" << chess.count << "}";
        break;
    }
    case ChessType::DF:
    {
        return "[东]";
    }
    case ChessType::XF:
    {
        return "[西]";
    }
    case ChessType::NF:
    {
        return "[南]";
    }
    case ChessType::BF:
    {
        return "[北]";
    }
    case ChessType::Zh:
    {
        return "[中]";
    }
    case ChessType::Fa:
    {
        return "[发]";
    }
    case ChessType::Bai:
    {
        return "[白]";
    }
    default:
        break;
    }
    return chessSS.str();
}


const std::string Utils::postion2Str(Postion ps)
{
    switch (ps)
    {
    case Postion::EAST:
        return "东";
    case Postion::NORTH:
        return "北";
    case Postion::WEST:
        return "西";
    case Postion::SOUTH:
        return "南";
    default:
        break;
    }
    return "";
}

const std::string Utils::roleType2Str(RoleType rt)
{
    switch (rt)
    {
    case RoleType::HOST:
        return "庄";
    case RoleType::CLIENT:
        return "闲";
    default:
        break;
    }
    return "";
}

const std::string Utils::sitPostionType2Str(SitPostion rt)
{
    switch (rt)
    {
    case MAIN:
        return "MAIN";
    case RIGHT:
        return "RIGHT";
    case TOP:
        return "TOP";
    case LEFT:
        return "LEFT";
    default:
        break;
    }
    return "MAIN";
}

const std::string Utils::chessStatusType2Str(ChessStatus rt)
{
    switch (rt)
    {
    case CHI:
        return "CHI";
    case PENG:
        return "PENG";
    case GANG:
        return "GANG";
    case ANGANG:
        return "ANGANG";
    case XUGANG:
        return "XUGANG";
    case HU:
        return "HU";
    case ZI_MO:
        return "ZI_MO";
    case EYE:
        return "EYE";
    case SHUN:
        return "SHUN";
    case EEE:
        return "EEE";
    default:
        break;
    }
    return "CHI";
}

short Utils::shakeDiceResult()
{
    std::random_device rd;
    return rd() % (6) + 1;
}

Postion Utils::getNextPlayerPsByDice(Postion startPs, short diceCunt)
{
    short sumDict = startPs + diceCunt;
    return s_postionArry[sumDict];
}

void Utils::getChessShowOffset(ShowOffsetPair* result, short maxReperoty, Postion& startPs, short startOffset)
{
    short eachPsotionCunt = maxReperoty / 4;
    if (eachPsotionCunt % 2 != 0)
    {
        eachPsotionCunt += 1;
    }
    short eachPostionChessCunt[SessionEnum::MAX_PLAYER_SIZE] =
    {
        eachPsotionCunt, eachPsotionCunt, eachPsotionCunt, (maxReperoty - (eachPsotionCunt * 3))
    };

    short tmpOffset = startOffset;
    if (tmpOffset >= eachPostionChessCunt[startPs])
    {
        tmpOffset = tmpOffset - eachPostionChessCunt[startPs];
        startPs = Utils::getNextShowPostion(startPs);
        startOffset = tmpOffset;
    }

    tmpOffset = maxReperoty - tmpOffset;
    short endOffset1 = eachPostionChessCunt[startPs] - (maxReperoty - tmpOffset);
    result[startPs].tailStartOffset = tmpOffset;
    result[startPs].tailEndOffset = maxReperoty;
    result[startPs].startOffset = 0;
    result[startPs].endOffset = endOffset1;

    Postion nextPs1 = Utils::getNextShowPostion(startPs);
    short endOffset2 = endOffset1 + eachPostionChessCunt[nextPs1];
    result[nextPs1].tailStartOffset = 0;
    result[nextPs1].tailEndOffset = 0;
    result[nextPs1].startOffset = endOffset1;
    result[nextPs1].endOffset = endOffset2;

    Postion nextPs2 = Utils::getNextShowPostion(nextPs1);
    short endOffset3 = endOffset2 + eachPostionChessCunt[nextPs2];
    result[nextPs2].tailStartOffset = 0;
    result[nextPs2].tailEndOffset = 0;
    result[nextPs2].startOffset = endOffset2;
    result[nextPs2].endOffset = endOffset3;

    Postion nextPs3 = Utils::getNextShowPostion(nextPs2);
    short endOffset4 = endOffset3 + eachPostionChessCunt[nextPs3];
    result[nextPs3].tailStartOffset = 0;
    result[nextPs3].tailEndOffset = 0;
    result[nextPs3].startOffset = endOffset3;
    result[nextPs3].endOffset = endOffset4;
}

SitPostion Utils::getPlayerSitPostion(Postion mainPs, Postion playerPs)
{
    if (mainPs == playerPs)
    {
        return SitPostion::MAIN;
    }

    auto rightPs = Utils::getNextDispatchPostion(mainPs);
    if (rightPs == playerPs)
    {
        return SitPostion::RIGHT;
    }

    auto topPs = Utils::getNextDispatchPostion(rightPs);
    if (topPs == playerPs)
    {
        return SitPostion::TOP;
    }

    auto leftPs = Utils::getNextDispatchPostion(topPs);
    if (leftPs == playerPs)
    {
        return SitPostion::LEFT;
    }
    return SitPostion::MAIN;
}

void Utils::setCursorPsn(short x, short y, const std::string& str)
{
    HANDLE outPutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD crd = { x,y };
    SetConsoleCursorPosition(outPutHandle, crd);
    std::cout << str;
}

void Utils::initBackGround()
{
    for (short i = 0; i < 90; i++)
    {
        Utils::setCursorPsn(i, 0, "+");
        Utils::setCursorPsn(i, 29, "+");
    }
    for (short i = 1; i < 30; i++)
    {
        Utils::setCursorPsn(0, i, "+");
        Utils::setCursorPsn(89, i, "+");
    }
}

void Utils::clearBackGround()
{
    for (short i = 1; i <= 88; i++)
    {
        for (short j = 1; j <= 28; j++)
        {
            Utils::setCursorPsn(i, j, " ");
        }
    }
}

void Utils::clearTable()
{
    for (size_t i = 16; i <= 71; i++)
    {
        for (size_t j = 2; j <= 27; j++)
        {
            Utils::setCursorPsn(i, j, " ");
        }
    }
}

void Utils::clearPlayTable()
{
    for (size_t x = 27; x <= 62; x++)
    {
        for (size_t y = 8; y <= 21; y++)
        {
            Utils::setCursorPsn(x, y, " ");
        }
    }
}

std::string Utils::sessionAction2Str(SessionAction sa)
{
    switch (sa)
    {
    case ACTION_DISPATH:
        return "发牌";
    case ACTION_OUTPUT:
        return "出牌";
    case ACTION_CHI:
        return "吃";
    case ACTION_PENG:
        return "碰";
    case ACTION_GANG:
        return "杠";
    case ACTION_ANGANG:
        return "暗杠";
    case ACTION_XUGANG:
        return "续杠";
    case ACTION_HU:
        return "胡";
    case ACTION_ZIMO:
        return "自摸";
    case ACTION_LIUJU:
        return "流局";
    default:
        break;
    }
    return std::string();
}

